package top.superflow.flow.runtime.process

import com.fasterxml.jackson.annotation.JsonIgnore
import top.superflow.exception.{Exceptable, FlowInitializeException}
import top.superflow.flow.runtime.Executable
import top.superflow.flow.runtime.inf.IOSchema
import top.superflow.flow.runtime.processprovider.{OriginalProcessProxy, RuntimeProcessProvider}

import scala.collection.Map

abstract class ExtProcess extends Executable[ProcessRequest, ProcessResponse] with Exceptable{

  @JsonIgnore
  private var originalProcess : OriginalProcessProxy = _

  private var provider : RuntimeProcessProvider = _

  def getProcessType : ProcessType.Value = ProcessType.PROCESS

  def getProvider = this.provider

  def setProvider(p : RuntimeProcessProvider) = this.provider = p

  def getInputSchema : IOSchema = {
    initOriginalProcess

    this.originalProcess.getInputSchema
  }

  def execute(request : ProcessRequest, response : ProcessResponse) = {

    val originalProcess = this.getOriginalProcess

    val expectedParameters = request.getParameters

    val result = originalProcess.execute(expectedParameters)

    fillResponse(result, response)
  }

  protected def getOriginalProcess : OriginalProcessProxy = {
    if(originalProcess != null){
      return this.originalProcess
    }

    initOriginalProcess

    originalProcess
  }


  def fillResponse(result : Any, response : ProcessResponse)


  private def initOriginalProcess: Unit = {
    if(this.provider == null){
      throw new FlowInitializeException("The process provider should not be null!")
    }

    if(this.originalProcess == null){
      originalProcess = this.provider.provide(this)
    }

    if(this.originalProcess == null){
      throwRequestUnsupportedException("The original process can't be initialized!")
    }
  }

  override def clone(): AnyRef = {
    val clonedProcess = super.clone().asInstanceOf[ExtProcess]

    val originalProcessProxy = clonedProcess.getOriginalProcess
    if(originalProcessProxy != null){
      val clonedOriginalProcessProxy = originalProcessProxy.clone().asInstanceOf[OriginalProcessProxy]
      clonedProcess.originalProcess = clonedOriginalProcessProxy
    }

    clonedProcess
  }

  override def mergeMetadata(newMetadata: Predef.Map[String, Any]): Unit = {
    super.mergeMetadata(newMetadata)
    if(this.originalProcess != null){
      this.originalProcess.mergeMetadata(newMetadata)
    }
  }

}

object ExtProcess{
  def main(args: Array[String]): Unit = {
    val map = Map[String, String]()
    
    
    println(map.get("abc").get)
  }
}